package com.zlq.cn.config.advice;

import cn.hutool.core.io.IoUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zlq.cn.bootstrap.SignApiBootstrap;
import com.zlq.cn.bootstrap.ValidateBootstrap;
import com.zlq.cn.config.Config;
import com.zlq.cn.dto.vo.SignCommonParam;
import lombok.extern.slf4j.Slf4j;
import one.util.streamex.StreamEx;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.util.Assert;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

@Slf4j
public class DecryptHttpInputMessage implements HttpInputMessage {

    private static final Charset CHARSET = StandardCharsets.UTF_8;

    private final HttpInputMessage inputMessage;
    private final boolean signEnable;
    private final int paramTimeOut;

    public DecryptHttpInputMessage(HttpInputMessage inputMessage, boolean signEnable, int paramTimeOut) {
        this.inputMessage = inputMessage;
        this.signEnable = signEnable;
        this.paramTimeOut = paramTimeOut * 1000;
    }

    @Override
    public InputStream getBody() throws IOException {
        String content = IoUtil.read(inputMessage.getBody(), CHARSET);
        log.info("本次请求参数：" + content);
        JSONObject jsonObject = JSON.parseObject(content);
        SignCommonParam fanYiCommonParam = jsonObject.toJavaObject(SignCommonParam.class);
        if (signEnable) {
            String validator = ValidateBootstrap.validator(fanYiCommonParam);
            Assert.isNull(validator, validator);
            String sign = StreamEx.of(jsonObject.keySet())
                    .sorted()
                    .map(key -> {
                        Object value = jsonObject.get(key);
                        if ("sign".equals(key) || value instanceof JSONObject || value instanceof JSONArray) {
                            return null;
                        }
                        return String.format("%s=%s", key, value);
                    })
                    .nonNull()
                    .append("md5key=" + Config.APP_MD5_KEY)
                    .joining("&");
            log.info("sign===>" + sign);
            String signData = SecureUtil.md5(sign);
            // 比对加密参数
            Assert.state(signData.equalsIgnoreCase(fanYiCommonParam.getSign()), "签名错误");
            // 校验时间戳
            Assert.state(System.currentTimeMillis() - fanYiCommonParam.getTimestamp() <= paramTimeOut, "参数超时");
        }
        SignApiBootstrap.set(fanYiCommonParam);
        return new ByteArrayInputStream(content.getBytes(CHARSET));
    }

    @Override
    public HttpHeaders getHeaders() {
        return inputMessage.getHeaders();
    }
}
